package com.kun.companion.core.queue;

import com.kun.companion.core.AbstractApplication;
import com.kun.companion.core.context.DestroyingBean;
import com.kun.companion.core.context.annotation.Autowired;
import com.kun.companion.core.context.annotation.Component;
import com.kun.companion.core.exception.BizException;
import com.kun.companion.core.thread.ComThreadPool;
import com.kun.companion.core.thread.PrioritizedTask;
import com.kun.companion.core.util.ComUtil;
import javafx.scene.control.Label;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.concurrent.*;

/**
 * 事件消息队列服务
 * <p>
 * 实现功能：
 * 1. 事件幂等性检查
 * 2. 优先级任务调度
 * 3. 线程池资源管理
 * 4. UI线程安全回调
 *
 * <p>核心流程：</p>
 * <pre>
 * UI事件提交 → 幂等性检查 → 任务封装 → 加入优先级队列 → 线程池执行 → 回调处理
 * </pre>
 *
 * @author gzc
 * @since 2025/2/3
 **/
@Component
public class EventMessageQueue implements DestroyingBean {
    private static final Logger log = LoggerFactory.getLogger(EventMessageQueue.class);
    /**
     * 事件注册表（线程安全）
     */
    private final Map<String, Boolean> eventRegistryMap = new ConcurrentHashMap<>(64);
    /**
     * 任务执行器（含优先级队列）
     */
//    private final TaskExecutor executor;
    /**
     * 独立的重试调度器（避免阻塞主线程池）
     */
    private final ScheduledExecutorService retryScheduler;
    @Autowired
    private ComThreadPool comThreadPool;

    /**
     * 默认配置构造器
     */
    public EventMessageQueue() {
        this.retryScheduler = Executors.newScheduledThreadPool(1);

//        this(QueueConfig.defaultConfig());
    }

    /**
     * 自定义配置构造器
     *
     * @param config 线程池配置参数
     */
//    public EventMessageQueue(QueueConfig config) {
//        this.executor = new TaskExecutor(config);
//        log.info("事件队列初始化完成，线程池配置: {}", config);
//    }

    /**
     * 提交事件到消息队列
     *
     * @param event           队列事件实例
     * @param successCallback 成功回调（在UI线程执行）
     * @param failureCallback 失败回调（在UI线程执行）
     * @return CompletableFuture 用于异步结果追踪
     */
    public CompletableFuture<Void> submitEvent(ButtonEvent event,
                                               Runnable successCallback,
                                               Runnable failureCallback) {
        CompletableFuture<Void> future = new CompletableFuture<>();
        String eventId = event.eventId();

        if (!registerEvent(eventId)) {
            handleImmediateFailure(eventId, future, failureCallback);
            return future;
        }

        submitTask(event,
                () -> handleSuccess(eventId, future, successCallback),
                () -> handleFailure(eventId, future, failureCallback));

        return future;
    }

    /**
     * 提交新任务到执行队列
     *
     * @param event   按钮事件（包含执行逻辑和优先级）
     * @param success 成功回调（在UI线程执行）
     * @param failure 失败回调（在UI线程执行）
     * @return Future对象可用于跟踪任务状态
     */
    public Future<?> submitTask(ButtonEvent event,
                                Runnable success,
                                Runnable failure) {
        // 包装为可优先执行的任务
        PrioritizedTask task = new PrioritizedTask(() -> {
            Label label = new Label("任务" + event.eventId() + "正在执行中..");
            try {
                AbstractApplication.updateRunningProgramList(label);
                // 执行核心逻辑
                event.execute();
                // 执行成功回调
                success.run();
            } catch (Throwable throwable) {
                handleFailure(event, throwable, success, failure);
            } finally {
                AbstractApplication.updateRunningProgramList(label);
            }
            // 设置任务优先级
        }, event.priority().getValue());

        return comThreadPool.submit(task);
    }

    /**
     * 失败处理逻辑（私有方法）
     */
    private void handleFailure(ButtonEvent event, Throwable throwable,
                               Runnable successCallback, Runnable failureCallback) {
        if (shouldRetry(event, throwable)) {
            resubmit(event, successCallback, failureCallback);
        } else {
            // 在UI线程执行失败回调
            ComUtil.uiThreadRun(() -> {
                failureCallback.run();
                log.error("任务执行失败:{} - ", event.eventId(), throwable);
            });
        }
    }

    /**
     * 注册事件（幂等性检查）
     */
    private boolean registerEvent(String eventId) {
        // 使用字符串驻留保证锁粒度
        synchronized (eventId.intern()) {
            if (eventRegistryMap.containsKey(eventId)) {
                log.warn("事件重复提交: {}", eventId);
                return false;
            }
            eventRegistryMap.put(eventId, true);
            log.debug("事件注册成功: {}", eventId);
            return true;
        }
    }

    /**
     * 处理立即失败情况
     */
    private void handleImmediateFailure(String eventId,
                                        CompletableFuture<Void> future,
                                        Runnable failureCallback) {
        failureCallback.run();
        future.completeExceptionally(new BizException("事件已存在: " + eventId));
        log.warn("事件立即失败: {}", eventId);
    }

    /**
     * 处理成功回调
     */
    private void handleSuccess(String eventId,
                               CompletableFuture<Void> future,
                               Runnable successCallback) {
        successCallback.run();
        future.complete(null);
        cleanupEvent(eventId);
        log.info("事件执行成功: {}", eventId);
    }

    /**
     * 处理失败回调
     */
    private void handleFailure(String eventId,
                               CompletableFuture<Void> future,
                               Runnable failureCallback) {
        failureCallback.run();
        future.completeExceptionally(new BizException("事件执行失败: " + eventId));
        cleanupEvent(eventId);
//        log.error("事件执行失败: {}", eventId);
    }

    /**
     * 清理事件注册记录
     */
    private void cleanupEvent(String eventId) {
        eventRegistryMap.remove(eventId);
        log.debug("事件清理完成: {}", eventId);
    }

    private int maxRetryAttempts = 3;

    /**
     * 判断是否需要重试（私有方法）
     */
    private boolean shouldRetry(ButtonEvent event, Throwable throwable) {
        // 检查异常类型是否可重试
        for (Class<?> exType : event.retryableExceptions()) {
            if (exType.isInstance(throwable)) {
                return event.getRetryCount() < maxRetryAttempts;
            }
        }
        return false;
    }

    /**
     * 调度重试任务（带指数退避）
     */
    private void resubmit(ButtonEvent event, Runnable successCallback, Runnable failureCallback) {
        event.incrementRetryCount();
        // 指数退避算法：2^retryCount 秒
        long delay = (1L << event.getRetryCount()) * 1000;
        // 使用独立调度器
        retryScheduler.schedule(() -> {
            log.info("重试任务 [ID:{}] 第{}次尝试", event.eventId(), event.getRetryCount());
            submitTask(event, successCallback, failureCallback);
        }, delay, TimeUnit.MILLISECONDS);
    }

    @Override
    public void destroy() {
        log.info("开始关闭事件队列...");
//        executor.shutdown();
        eventRegistryMap.clear();
        log.info("事件队列已关闭，剩余事件: {}", eventRegistryMap.size());
    }
}
